package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.search.query.SearchQueryObject;
import cn.wolfcode.luowowo.search.reporsitory.IStrategySearchRepository;
import cn.wolfcode.luowowo.search.service.IStrategySearchService;
import cn.wolfcode.luowowo.search.templates.StrategyTemplate;
import cn.wolfcode.luowowo.search.vo.StatisVO;
import com.alibaba.dubbo.config.annotation.Service;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregation;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeValuesSourceBuilder;
import org.elasticsearch.search.aggregations.bucket.composite.TermsValuesSourceBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;

import java.util.*;

@Service
public class StrategySearchServiceImpl implements IStrategySearchService{
    @Autowired
    private IStrategySearchRepository dao;
    @Autowired
    private ElasticsearchTemplate template;
    @Autowired
    private TransportClient client;
    //创建索引
    public void createIndex() {
        template.createIndex(StrategyTemplate.class);
        template.putMapping(StrategyTemplate.class);
    }

    public void initData() {

    }

    public void save(StrategyTemplate t) {
        dao.save(t);
    }

    public List<Map<String, Object>> queryThemeCommends() {
        /*
        "size": 0,
  "aggs": {
    "themeGroup": {
      "composite": {
        "sources": [
          {
            "id": {
              "terms": {
                "field": "themeId"
              }
            }
          },
          {"name":{
            "terms": {
              "field": "themeName"
            }
          }}
        ]*/
        List<StatisVO> themeVos = this.statisGroup("themeId", "themeName", "themeGroup", null);
        if(themeVos.size() > 10){
            themeVos = (ArrayList<StatisVO>) themeVos.subList(0, 10);
        }
        //外层list
        ArrayList<Map<String,Object>> data = new ArrayList<>();
        //内层:主题+目的地结合
        Map<String,Object> map;
        //里层目的地部分
        for (StatisVO vo : themeVos) {
           List<StatisVO> list =  queryDestByThemeId(vo.getId());
           map =  new HashMap<>();
           map.put("theme",vo);
           map.put("dests",list);
           data.add(map);
        }
        return data;
    }

    public List<StatisVO> queryStrategyCondition(int conditionType) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        String idField = "";
        String nameField = "";

        if(conditionType == SearchQueryObject.CONDITION_TYPE_ABROAD){
            idField = "countryId";
            nameField = "countryName";
            boolQueryBuilder.mustNot(QueryBuilders.termQuery("countryId",1));

        }else if(conditionType == SearchQueryObject.CONDITION_TYPE_UN_ABROAD){
            idField = "provinceId";
            nameField = "provinceName";
            boolQueryBuilder.must(QueryBuilders.termQuery("countryId",1));
        }else{
            idField = "themeId";
            nameField = "themeName";
        }
        List<StatisVO> themeVos = this.statisGroup(idField, nameField, "conditionGroup", boolQueryBuilder);
        return themeVos;
    }
    //最受欢迎....查询
    public Page<StrategyTemplate> query(SearchQueryObject qo) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        if(qo.getType() == SearchQueryObject.CONDITION_TYPE_ABROAD){
            boolQuery.must(QueryBuilders.termQuery("countryId",qo.getTypeValue()));

        }else if(qo.getType() == SearchQueryObject.CONDITION_TYPE_UN_ABROAD){
            boolQuery.must(QueryBuilders.termQuery("provinceId",qo.getTypeValue()));
        }else if(qo.getType() == SearchQueryObject.CONDITION_TYPE_THEME){
            boolQuery.must(QueryBuilders.termQuery("themeId",qo.getTypeValue()));
        }
        Page<StrategyTemplate> page = dao.search(boolQuery, qo.getPageable());
        return page;
    }

    public Page<StrategyTemplate> queryByDestId(SearchQueryObject qo) {
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        if(qo.getDestId() != -1){
            query.must(QueryBuilders.termQuery("destId",qo.getDestId()));
        }
        return dao.search(query,qo.getPageableWithoutSort());
    }




    private List<StatisVO> queryDestByThemeId(Long themeId) {
        ArrayList<StatisVO> list = new ArrayList<>();
        ArrayList<String> names = new ArrayList<>();//去除重复
        Iterable<StrategyTemplate> iterable = dao.search(QueryBuilders.termQuery("themeId", themeId));

        iterable.forEach(s ->{
            if(!names.contains(s.getDestName())){
                StatisVO vo = new StatisVO();
                vo.setId(s.getId());
                vo.setName(s.getDestName());
                list.add(vo);
                names.add(s.getDestName());
            }

        });
        return list;
    }
    //抽取公共的代码
    public List<StatisVO> statisGroup(String idField, String nameField, String groupName, BoolQueryBuilder query){
        ArrayList<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();
        //构建分组字段对象
        TermsValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id");
        idSource.field(idField).missingBucket(true);
        TermsValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name");
        nameSource.field(nameField).missingBucket(true);
        sources.add(idSource);
        sources.add(nameSource);
        if(query == null){
            query = QueryBuilders.boolQuery();
        }
        //设置分组名称和分组字段结合
        CompositeAggregationBuilder builder = new CompositeAggregationBuilder(groupName, sources);
        //创建查询请求对象,设置索引
        SearchRequest request = new SearchRequest(StrategyTemplate.INDEX_NAME);
        //设置类型
        request.types(StrategyTemplate.TYPE_NAME).source(new SearchSourceBuilder()
                .aggregation(builder).query(query).size(0));
        //发起请求,获取结果
        SearchResponse response = this.client.search(request).actionGet();
        //解析结果
        Aggregations aggregations = response.getAggregations();
        CompositeAggregation compositeAggregation = aggregations.get(groupName);
        List<? extends CompositeAggregation.Bucket> buckets = compositeAggregation.getBuckets();
        ArrayList<StatisVO> themeVos = new ArrayList<>();
        for (CompositeAggregation.Bucket bucket : buckets) {
            StatisVO vo = new StatisVO();
            Map<String, Object> key = bucket.getKey();
            vo.setId(Long.valueOf(key.get("id").toString()));
            vo.setName(key.get("name").toString());
            vo.setCount(bucket.getDocCount());
            themeVos.add(vo);
        }
        //排序
        Collections.sort(themeVos, new Comparator<StatisVO>() {
            public int compare(StatisVO o1, StatisVO o2) {
                return o2.getCount().compareTo(o1.getCount());
            }
        });
        return themeVos;
    }
}
